#pragma once
#ifndef CLASS_ANGLE_INTER 
#define CLASS_ANGLE_INTER
#include <string> 
#include <iostream>
#include <vector>
#include <algorithm>

#include "TH1.h"
#include "TSystem.h"
#include "TStyle.h"
#include "TCanvas.h"
#include "TChain.h"
#include "TClonesArray.h"
#include "TLorentzVector.h"

#include "src/Lib/MessageFormat.h"
#include "AComb_LTV.h"

class AComb_Angle_Inter{
	private:
		bool                     _has_LTV;
		AComb_LTV                _A, _B;
		std::string              _title;
		int _num_out1_out1  , _num_out1_out2  , _num_out1_comb , _num_out1_left1  , _num_out1_left2;
		int _num_out2_out1  , _num_out2_out2  , _num_out2_comb , _num_out2_left1  , _num_out2_left2;
		int _num_comb_out1  , _num_comb_out2  , _num_comb_comb , _num_comb_left1  , _num_comb_left2;
		int _num_left1_out1 , _num_left1_out2 , _num_left1_comb, _num_left1_left1 , _num_left1_left2;
		int _num_left2_out1 , _num_left2_out2 , _num_left2_comb, _num_left2_left1 , _num_left2_left2;
		int _num;
	public:
		AComb_Angle_Inter(){
			_has_LTV = false;
			_title = "";
			_num_out1_out1 = 0, _num_out1_out2 = 0, _num_out1_comb = 0, _num_out1_left1 = 0, _num_out1_left2 = 0;
			_num_out2_out1 = 0, _num_out2_out2 = 0, _num_out2_comb = 0, _num_out2_left1 = 0, _num_out2_left2 = 0;
			_num_comb_out1 = 0, _num_comb_out2 = 0, _num_comb_comb = 0, _num_comb_left1 = 0, _num_comb_left2 = 0;
			_num_left1_out1= 0, _num_left1_out2= 0, _num_left1_comb= 0, _num_left1_left1= 0, _num_left1_left2= 0;
			_num_left2_out1= 0, _num_left2_out2= 0, _num_left2_comb= 0, _num_left2_left1= 0, _num_left2_left2= 0;
			_num = 0;
		};

		std::vector<double> out1_out1_angle;
		std::vector<double> out1_out2_angle;
		std::vector<double> out1_comb_angle;
		std::vector<double> out1_left1_angle;
		std::vector<double> out1_left2_angle;

		std::vector<double> out2_out1_angle;
		std::vector<double> out2_out2_angle;
		std::vector<double> out2_comb_angle;
		std::vector<double> out2_left1_angle;
		std::vector<double> out2_left2_angle;

		std::vector<double> comb_out1_angle;
		std::vector<double> comb_out2_angle;
		std::vector<double> comb_comb_angle;
		std::vector<double> comb_left1_angle;
		std::vector<double> comb_left2_angle;

		std::vector<double> left1_out1_angle;
		std::vector<double> left1_out2_angle;
		std::vector<double> left1_comb_angle;
		std::vector<double> left1_left1_angle;
		std::vector<double> left1_left2_angle;

		std::vector<double> left2_out1_angle;
		std::vector<double> left2_out2_angle;
		std::vector<double> left2_comb_angle;
		std::vector<double> left2_left1_angle;
		std::vector<double> left2_left2_angle;


		void Assign_Variables(CDraw &para, AVariable &var);
		void Set_Variables(AComb_LTV &input1, AComb_LTV &input2);
		void Set_Angle();
		int  Num(std::string name="");
		void Print(int level = 2, std::string str="");

};

class AComb_DeltaR_Inter{
	private:
		bool                     _has_LTV;
		AComb_LTV                _A, _B;
		std::string              _title;
	public:
		AComb_DeltaR_Inter(){
			_has_LTV = false;
			_title = "";
		};

		std::vector<double> out1_out1_DeltaR;
		std::vector<double> out1_out2_DeltaR;
		std::vector<double> out1_comb_DeltaR;
		std::vector<double> out1_left1_DeltaR;
		std::vector<double> out1_left2_DeltaR;

		std::vector<double> out2_out1_DeltaR;
		std::vector<double> out2_out2_DeltaR;
		std::vector<double> out2_comb_DeltaR;
		std::vector<double> out2_left1_DeltaR;
		std::vector<double> out2_left2_DeltaR;

		std::vector<double> comb_out1_DeltaR;
		std::vector<double> comb_out2_DeltaR;
		std::vector<double> comb_comb_DeltaR;
		std::vector<double> comb_left1_DeltaR;
		std::vector<double> comb_left2_DeltaR;

		std::vector<double> left1_out1_DeltaR;
		std::vector<double> left1_out2_DeltaR;
		std::vector<double> left1_comb_DeltaR;
		std::vector<double> left1_left1_DeltaR;
		std::vector<double> left1_left2_DeltaR;

		std::vector<double> left2_out1_DeltaR;
		std::vector<double> left2_out2_DeltaR;
		std::vector<double> left2_comb_DeltaR;
		std::vector<double> left2_left1_DeltaR;
		std::vector<double> left2_left2_DeltaR;


		void Assign_Variables(CDraw &para, AVariable &var);
		void Set_Variables(AComb_LTV &input1, AComb_LTV &input2);
		void Set_DeltaR();
		void Print(int level = 2, std::string str="");

};

class AComb_DeltaPhi_Inter{
	private:
		bool                     _has_LTV;
		AComb_LTV                _A, _B;
		std::string              _title;
	public:
		AComb_DeltaPhi_Inter(){
			_has_LTV = false;
			_title = "";
		};

		std::vector<double> out1_out1_DeltaPhi;
		std::vector<double> out1_out2_DeltaPhi;
		std::vector<double> out1_comb_DeltaPhi;
		std::vector<double> out1_left1_DeltaPhi;
		std::vector<double> out1_left2_DeltaPhi;

		std::vector<double> out2_out1_DeltaPhi;
		std::vector<double> out2_out2_DeltaPhi;
		std::vector<double> out2_comb_DeltaPhi;
		std::vector<double> out2_left1_DeltaPhi;
		std::vector<double> out2_left2_DeltaPhi;

		std::vector<double> comb_out1_DeltaPhi;
		std::vector<double> comb_out2_DeltaPhi;
		std::vector<double> comb_comb_DeltaPhi;
		std::vector<double> comb_left1_DeltaPhi;
		std::vector<double> comb_left2_DeltaPhi;

		std::vector<double> left1_out1_DeltaPhi;
		std::vector<double> left1_out2_DeltaPhi;
		std::vector<double> left1_comb_DeltaPhi;
		std::vector<double> left1_left1_DeltaPhi;
		std::vector<double> left1_left2_DeltaPhi;

		std::vector<double> left2_out1_DeltaPhi;
		std::vector<double> left2_out2_DeltaPhi;
		std::vector<double> left2_comb_DeltaPhi;
		std::vector<double> left2_left1_DeltaPhi;
		std::vector<double> left2_left2_DeltaPhi;


		void Assign_Variables(CDraw &para, AVariable &var);
		void Set_Variables(AComb_LTV &input1, AComb_LTV &input2);
		void Set_DeltaPhi();
		void Print(int level = 2, std::string str="");

};


class AComb_Inter{
	private:
		bool                     _has_LTV;
		AComb_LTV                _A, _B;
		std::string              _title;
		int _num_out1_out1  , _num_out1_out2  , _num_out1_comb , _num_out1_left1  , _num_out1_left2;
		int _num_out2_out1  , _num_out2_out2  , _num_out2_comb , _num_out2_left1  , _num_out2_left2;
		int _num_comb_out1  , _num_comb_out2  , _num_comb_comb , _num_comb_left1  , _num_comb_left2;
		int _num_left1_out1 , _num_left1_out2 , _num_left1_comb, _num_left1_left1 , _num_left1_left2;
		int _num_left2_out1 , _num_left2_out2 , _num_left2_comb, _num_left2_left1 , _num_left2_left2;
		int _num;
	public:
		AComb_Angle_Inter        angle;
		AComb_DeltaR_Inter       deltar;
		AComb_DeltaPhi_Inter     deltaphi;

		std::map<std::string, bool> angle_switch;
		AComb_Inter(){
			_has_LTV = false;
			_title = "";
			_num_out1_out1 = 0, _num_out1_out2 = 0, _num_out1_comb = 0, _num_out1_left1 = 0, _num_out1_left2 = 0;
			_num_out2_out1 = 0, _num_out2_out2 = 0, _num_out2_comb = 0, _num_out2_left1 = 0, _num_out2_left2 = 0;
			_num_comb_out1 = 0, _num_comb_out2 = 0, _num_comb_comb = 0, _num_comb_left1 = 0, _num_comb_left2 = 0;
			_num_left1_out1= 0, _num_left1_out2= 0, _num_left1_comb= 0, _num_left1_left1= 0, _num_left1_left2= 0;
			_num_left2_out1= 0, _num_left2_out2= 0, _num_left2_comb= 0, _num_left2_left1= 0, _num_left2_left2= 0;
			_num = 0;
		};

		AComb_Inter(AComb_LTV &input1, AComb_LTV &input2){
			_A = input1;
			_B = input2;
			_title = "Inter for "+input1.Title() + " + " + input2.Title();
			_has_LTV = true;

			angle   .Set_Variables(input1, input2);
			deltar  .Set_Variables(input1, input2);
			deltaphi.Set_Variables(input1, input2);
		};

		void Assign_Variables(CDraw &para, AVariable &var){
			angle   .Assign_Variables(para, var);
			deltar  .Assign_Variables(para, var);
			deltaphi.Assign_Variables(para, var);
		}

		void Set_Variables();

		void Set_Variables(AComb_LTV &input1, AComb_LTV &input2);

		void Set_Angle_Switch();

		void Set_Distance();

		int  Num(std::string name="");

		AComb_LTV  A(){
			return(_A);
		}

		AComb_LTV  B(){
			return(_B);
		}

		void Print(int level = 2, std::string name="");


};
#endif
